//
//  CorP5eSession.m
//  CorP5e
//
//  Created by Matthew Giant on 9/27/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "CorP5eSession.h"
#import "CorP5eFilter.h"
#import "CorP5eMovie.h"

/** static pointer for session instance **/
CorP5eSession *gSession = NULL;

/** session tracks and manipulated Obj-C created objects **/
@implementation CorP5eSession

/** get singleton instance, create if needed **/
+ (CorP5eSession *)instance
{
	if ( !gSession )
	{
		gSession = [[CorP5eSession alloc] init];
	}
	
	return gSession;
}

- (id)init
{
	if ( self = [super init] )
	{
		seqId = 0;
		
		corP5eObjects = [[NSMutableDictionary dictionaryWithCapacity:10] retain];

		defaultSpace = CGColorSpaceCreateDeviceRGB();
		
		[CIPlugIn loadAllPlugIns];
		
		[self performSelectorOnMainThread:@selector(qtMovieInit) withObject:nil waitUntilDone:YES];
	}

	return self;
}


- (void)dealloc
{
	[corP5eObjects release];
	CGColorSpaceRelease( defaultSpace );
	[super dealloc];
}

- (void)qtMovieInit
{
	[QTMovie movie];
}

/** create a new filter based on filter name, stores in filters dictionary if successful **/
- (NSUInteger)createFilter:( NSString *)filterName
{
	NSUInteger filterId = -1;
	
	CorP5eFilter *filter = [[CorP5eFilter alloc] initWithFilterName:filterName];
		//instantiate filter wrapper with provided name
	
	//if CIFilter was instantiated
	if ( filter.filter )
	{
		filterId = seqId++;
			//get an id from sequence
	
		[corP5eObjects setObject:filter forKey:[NSNumber numberWithUnsignedInteger:filterId]];
			//add filter to filters dictionary keyed by id
	}

	[filter release];
	
	return filterId;
		//failed to create filter, return -1 as error
}

/** looks up and returns an existing filter wrapper **/
- (CorP5eFilter *)filterWithId:(NSUInteger)aFilterId
{
	NSUInteger filterId = (NSUInteger)aFilterId;
	
	return [corP5eObjects objectForKey:[NSNumber numberWithUnsignedInteger:filterId]];
}

- (void)storeImage:(CIImage *)image
{
	
}

- (void)removeObjectWithId:(NSUInteger)filterId
{
	[corP5eObjects removeObjectForKey:[NSNumber numberWithUnsignedInteger:filterId]];
}

- (void)compileKernels:(NSString *)kernelText
{
	NSArray *kernels = [CIKernel kernelsWithString:kernelText];
}


/** returns a CIImage based on the passed in java/PImage formated data **/
- (CIImage *)makeCIImageWithFormat:(int)pixelFormat
							 width:(NSUInteger)width
							height:(NSUInteger)height
							pixels:(UInt32 *)pixels
{
	CVPixelBufferRef pixelBuffer;
	
	CVReturn result = CVPixelBufferCreateWithBytes(	NULL,
													width,
													height,
													kCVPixelFormatType_32BGRA,
													pixels,
													sizeof(	UInt32 ) * width,
													NULL,
													NULL,
													NULL,
													&pixelBuffer );
	if ( result )
	{
		NSLog( @"CVPixelBufferCreateWithBytes returned %d.\n", result );
		return nil;
	}
	
	
	CIImage *img = [CIImage imageWithCVImageBuffer:pixelBuffer];
	
	CVPixelBufferRelease( pixelBuffer );

	return img;
}

/** returns a CGImage based on the passed in java/PImage formated data **/
- (CGImageRef)makeCGImageWithFormat:(int)pixelFormat
							  width:(NSUInteger)width
							 height:(NSUInteger)height
							 pixels:(UInt32 *)pixels
{
	/// create image by using input data as buffer for a context then fetching an image

	//create context in 8bit/channel RGBA big edian mode as needed for java/processing 
	CGContextRef bmp = CGBitmapContextCreate(	pixels, 
												width,
												height, 
												8,
												sizeof( UInt32 ) * width, 
												defaultSpace, 
												kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst );
	
	CGImageRef img = CGBitmapContextCreateImage( bmp );
	
	CGImageRef copy = CGImageCreateCopy( img );
	
	CGImageRelease( img );
	CGContextRelease( bmp );

	return copy;
}

/*- (void)fillPImage:(PImageStruct *)pimg 
	   withCIImage:(CIImage *)img*/
- (void)renderImage:(CIImage *)img 
			   rect:(CGRect)rect 
		   toBuffer:(void *)buffer 
{
	//create context in 8bit/channel RGBA big edian mode as needed for java/processing 
	CGContextRef bmp = CGBitmapContextCreate(	buffer, 
												rect.size.width,
												rect.size.height, 
												8,
												sizeof( UInt32 ) * rect.size.width, 
												defaultSpace, 
												kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst );

	CIContext *ciContext = [CIContext contextWithCGContext:bmp options:nil];
	
	[ciContext drawImage:img inRect:rect fromRect:rect];
	
	CGContextRelease( bmp );
}

/** create a movie with just width/height and frame rate **/
- (NSUInteger)createMovieWithInfo:(CorP5eMovieInfo *)info
{
	CorP5eMovie *movie = [CorP5eMovie alloc];
	
	[movie performSelectorOnMainThread:@selector( initWithInfo: ) withObject:info waitUntilDone:YES ];
	
	if ( !movie )
	{
		return -1;
	}
	
	NSUInteger movieId = seqId++;
	
	[corP5eObjects setObject:movie forKey:[NSNumber numberWithUnsignedInteger:movieId]];
	//add movie to CorP5e objects dictionary keyed by id
	
	[movie release];
	
	return movieId;
}

- (CorP5eMovie *)movieWithId:(NSUInteger)movieId
{
	return (CorP5eMovie *)[corP5eObjects objectForKey:[NSNumber numberWithUnsignedInt:movieId]];
}


@end
					
							